/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frprotocol_detect.c                                */
/*  NOTE      = 协议判断                                           */
/*  DATE      = 2014/10/29                                         */
/*******************************************************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <dlfcn.h>

#include "frcomm.h"
#include "frmem.h"
#include "frstr.h"
#include "frlog.h"
#include "conntrack.h"
#include "frame.h"
#include "frame_params.h"
#include "module.h"
#include "frct_comm.h"
#include "frct_mng.h"
#include "frmodule_mng.h"
#include "frproto_mng.h"
#include "frproto_l7default.h"
#include "frstat_module.h"
#include "frstat_system.h"
#include "frstat_server.h"

/*******************************************************************************
*  FUNC     :  追加识别协议到ct上
*  ARGS     :  p_st_ct              (Conntrack *)
*           :  p_st_list_hdr_define (指定的管理协议链Frmodule_mng)
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frct_l7proto_add_lst(Conntrack *p_st_ct, Frlist_header *p_st_list_hdr_define)
{
    Frlist_node *p_st_node_l7proto=NULL, *p_st_node_define=NULL;
    Frmodule_mng *p_st_module_mng=NULL;
    
    if(p_st_ct == NULL || p_st_list_hdr_define == NULL || frlist_size(p_st_list_hdr_define) <=0 )
        return FR_FAIL;
    
    p_st_node_define = frlist_pop(p_st_list_hdr_define);
    while(p_st_node_define)
    {
        p_st_module_mng = (Frmodule_mng *)FRLIST_GET_NODE_DATA(p_st_node_define);
        if(p_st_module_mng)
        {
            p_st_node_l7proto = frct_l7proto_node_mk( &p_st_module_mng->st_l7_module);
            frlist_push(&p_st_ct->lst_hdr_l7proto, p_st_node_l7proto);
            frstat_system_module_conn_add(p_st_module_mng->st_l7_module.i_l7_proto, 0, 1, 0, 0);
            frstat_server_add(p_st_ct->dst_ip, p_st_ct->dst_port, p_st_module_mng->st_l7_module.i_l7_proto, 1, 0, 0);
        }

        frlist_node_free(p_st_list_hdr_define, p_st_node_define, FR_NO, NULL );
        p_st_node_define = frlist_pop(p_st_list_hdr_define);
    }
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  协议增加到ct->lst_hdr_l7_proto链中
*  ARGS     :  p_st_hdr_l7_proto    (&ct->lst_hdr_l7proto)
*           :  p_st_l7_module       (L7_module *)
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frct_l7proto_add_one(Conntrack *p_st_ct, L7_module *p_st_l7_module)
{
    Frlist_node *p_st_l7_proto_node = NULL;

    if(p_st_ct == NULL || p_st_l7_module == NULL)
        return FR_FAIL;

    p_st_l7_proto_node = FRLIST_LAST_NODE(&p_st_ct->lst_hdr_l7proto);
    if(p_st_l7_proto_node == NULL) //没有没有时追加
    {
        p_st_l7_proto_node =frct_l7proto_node_mk(p_st_l7_module);
        frlist_push(&p_st_ct->lst_hdr_l7proto, p_st_l7_proto_node);
        frstat_system_module_conn_add(p_st_l7_module->i_l7_proto, 0, 1, 0, 0);
        frstat_server_add(p_st_ct->dst_ip, p_st_ct->dst_port, p_st_l7_module->i_l7_proto, 1, 0, 0);
    }
    else
    {
        L7_analyzer *p_st_l7_analyzer= (L7_analyzer *)FRLIST_GET_NODE_DATA(p_st_l7_proto_node);
        if(p_st_l7_analyzer == NULL)
            return FR_FAIL;
        //没有解析协议
        if(p_st_l7_analyzer->p_st_l7_module == NULL)
            p_st_l7_analyzer->p_st_l7_module = p_st_l7_module;
        else //增加新节点
        {
            p_st_l7_proto_node =frct_l7proto_node_mk(p_st_l7_module);
            frlist_push(&p_st_ct->lst_hdr_l7proto, p_st_l7_proto_node);
        }
        frstat_system_module_conn_add(p_st_l7_module->i_l7_proto, 0, 1, 0, 0);
        frstat_server_add(p_st_ct->dst_ip, p_st_ct->dst_port, p_st_l7_module->i_l7_proto, 1, 0, 0);
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  增加1个空节点到ct->lst_hdr_l7_proto中
*  ARGS     :  p_st_hdr_l7_proto    (&ct->lst_hdr_l7proto)
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :
*******************************************************************************/
int frct_l7proto_add_empty(Conntrack *p_st_ct)
{
    Frlist_node *p_st_l7_proto_node = NULL, *p_st_node_l7proto_empty=NULL;
    L7_analyzer *p_st_l7_analyzer;

    if(p_st_ct == NULL)
        return FR_FAIL;

    p_st_l7_proto_node = FRLIST_LAST_NODE(&p_st_ct->lst_hdr_l7proto);
    if(p_st_l7_proto_node == NULL) //没有时追加
    {
        p_st_node_l7proto_empty = frct_l7proto_node_mk( NULL);
        if(p_st_node_l7proto_empty == NULL)
        {
            FRLOG_ERROR_DETAIL("frct_l7_proto_node_mk err");
            return FR_FAIL;
        }
        frlist_push(&p_st_ct->lst_hdr_l7proto, p_st_node_l7proto_empty);
        return FR_SUCC;
    }

    p_st_l7_analyzer= (L7_analyzer *)FRLIST_GET_NODE_DATA(p_st_l7_proto_node);
    if(p_st_l7_analyzer == NULL)
    {
        //不应该有这种情况
        FRLOG_ERROR_DETAIL("p_st_l7_analyzer is null, impossible");
        return FR_FAIL;
    }

    if(p_st_l7_analyzer->p_st_l7_module == NULL)
        return FR_SUCC;

    p_st_node_l7proto_empty = frct_l7proto_node_mk( NULL);
    if(p_st_node_l7proto_empty == NULL)
    {
        FRLOG_ERROR_DETAIL("frct_l7_proto_node_mk err");
        return FR_FAIL;
    }
    frlist_push(&p_st_ct->lst_hdr_l7proto, p_st_node_l7proto_empty);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  从指定位置开始删除解析协议时，更新统计信息
*  ARGS     :  p_st_ct              (Conntrack *)
*           :  ui_idx               (协议从0开始)
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frct_stat_system_lst_update(Conntrack *p_st_ct
                                          , unsigned int ui_idx
                                          , int i_syn
                                          , int i_established
                                          , int i_disconnect
                                          , int i_destroy)
{
    Frlist_node *p_st_node=NULL;
    L7_analyzer *p_st_l7_analyzer;
    int i_loop=0;

    if(p_st_ct==NULL)
        return FR_FAIL;

    p_st_node = FRLIST_FIRST_NODE(&p_st_ct->lst_hdr_l7proto);

    i_loop=0;
    while(p_st_node)
    {
        p_st_l7_analyzer =  (L7_analyzer*)FRLIST_GET_NODE_DATA(p_st_node);
        if(p_st_l7_analyzer == NULL || p_st_l7_analyzer->p_st_l7_module == NULL)
            break;

        if(i_loop++ < ui_idx)
        {
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
            continue;
        }

        frstat_system_module_conn_add(p_st_l7_analyzer->p_st_l7_module->i_l7_proto, i_syn, i_established, i_disconnect, i_destroy);
        frstat_server_add(p_st_ct->dst_ip, p_st_ct->dst_port, p_st_l7_analyzer->p_st_l7_module->i_l7_proto, i_established-i_disconnect-i_destroy, 0, 0);
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  从指定位置开始删除解析协议时，更新统计信息
*  ARGS     :  p_st_hdr_l7_proto    (Frlist_header *)
*           :  ui_idx               (协议从0开始)
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :  需要加锁( p_st_ct->lock)
*******************************************************************************/
int frct_stat_system_lst_update(Conntrack *p_st_ct
                              , unsigned int ui_idx
                              , int i_syn
                              , int i_established
                              , int i_disconnect
                              , int i_destroy)
{
    return __frct_stat_system_lst_update(p_st_ct, ui_idx, i_syn, i_established, i_disconnect, i_destroy);
}

/*******************************************************************************
*  FUNC     :  通过比较L7_module模块,更新ct上已经识别的协议
*  ARGS     :  p_st_ct              (Conntrack *)
*           :  p_st_list_hdr_define (指定的管理协议链Frmodule_mng)
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :
*******************************************************************************/
FR_STATIC int __frct_l7proto_update_lst(Conntrack *p_st_ct, Frlist_header *p_st_list_hdr_define)
{
    Frlist_header *p_lst_hdr_l7proto=NULL;
    Frlist_node *p_st_node_l7proto=NULL, *p_st_node_define=NULL;
    L7_analyzer *p_st_l7_analyzer=NULL;
    Frmodule_mng *p_st_module_mng=NULL;
    int i_loop=0, i_count=0, i_node_free_idx=-1;
    
    if(p_st_ct == NULL || p_st_list_hdr_define == NULL)
        return FR_FAIL;
    p_lst_hdr_l7proto = &p_st_ct->lst_hdr_l7proto;
    
    //释放p_lst_hdr_l7_proto与p_st_list_hdr_define不同的协议
    i_count = frlist_size(p_lst_hdr_l7proto);
    if(i_count > frlist_size(p_st_list_hdr_define) )
        i_count = frlist_size(p_st_list_hdr_define);
    
    //判断协议不同的位置
    for(i_loop = 0; i_loop < i_count; i_loop++)
    {
        p_st_node_l7proto = frlist_node_idx(p_lst_hdr_l7proto, i_loop);
        p_st_node_define  = frlist_node_idx(p_st_list_hdr_define, i_loop);
        
        if(p_st_node_l7proto == NULL || p_st_node_define==NULL)
        {
            i_node_free_idx = i_loop;
            break;
        }
        
        p_st_l7_analyzer = (L7_analyzer *)FRLIST_GET_NODE_DATA(p_st_node_l7proto);
        p_st_module_mng = (Frmodule_mng *)FRLIST_GET_NODE_DATA(p_st_node_define);
        if(p_st_l7_analyzer == NULL || p_st_l7_analyzer->p_st_l7_module == NULL
            || p_st_module_mng==NULL )
        {
            i_node_free_idx = i_loop;
            break;
        }
        
        if(p_st_l7_analyzer->p_st_l7_module != &p_st_module_mng->st_l7_module )
        {
            i_node_free_idx = i_loop;
            break;
        }
    }
    
    if(i_node_free_idx == -1 )
    {
        //完全一样
        if(frlist_size(p_lst_hdr_l7proto) == frlist_size(p_st_list_hdr_define))
            return FR_SUCC;
        //释放多余节点
        if(i_node_free_idx == -1 && frlist_size(p_lst_hdr_l7proto) > frlist_size(p_st_list_hdr_define))
        {
            __frct_stat_system_lst_update(p_st_ct, frlist_size(p_st_list_hdr_define), 0, -1, 0, 0);
            frlist_remove_from_idx(p_lst_hdr_l7proto, frlist_size(p_st_list_hdr_define), frct_l7proto_node_free);
        }
    }
    else if(i_node_free_idx == 0 )
    {
        //全部不一致
        __frct_stat_system_lst_update(p_st_ct, 0, 0, -1, 0, 0);
        frlist_remove_all(p_lst_hdr_l7proto,frct_l7proto_node_free);
    }
    else
    {
        //部分不一致
        __frct_stat_system_lst_update(p_st_ct, i_node_free_idx, 0, -1, 0, 0);
        frlist_remove_from_idx(p_lst_hdr_l7proto, i_node_free_idx, frct_l7proto_node_free);
        for(i_loop=0; i_loop < i_node_free_idx; i_loop++)
        {
            p_st_node_define = frlist_pop(p_st_list_hdr_define);
            frlist_node_free(p_st_list_hdr_define, p_st_node_define, FR_NO, NULL );
        }
    }
    
    //追加到ct的协议链上
    __frct_l7proto_add_lst(p_st_ct, p_st_list_hdr_define);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  从指定位置开始删除解析协议
*  ARGS     :  p_st_ct              (Conntrack *)
*           :  ui_idx               (协议从0开始；如果要全部删除，ui_idx=0即可)
*  RTN      :  删除协议个数
*  NOTE     :
*******************************************************************************/
int frct_l7proto_remove(Conntrack *p_st_ct, unsigned int ui_idx)
{
    int i_ret_cnts=0, i_total=0;

    if(p_st_ct == NULL)
        return 0;

    i_total = frlist_size(&p_st_ct->lst_hdr_l7proto);
    i_ret_cnts = i_total - ui_idx;
    if(i_ret_cnts <= 0)
        return 0;

    __frct_stat_system_lst_update(p_st_ct, ui_idx, 0, -1, 0, 0);
    if(ui_idx == 0)
        frlist_remove_all(&p_st_ct->lst_hdr_l7proto ,frct_l7proto_node_free);
    else
        frlist_remove_from_idx(&p_st_ct->lst_hdr_l7proto, ui_idx, frct_l7proto_node_free);
    return i_ret_cnts;
}

/*******************************************************************************
*  FUNC     :  释放协议
*  ARGS     :  p_st_ct              (Conntrack *)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frct_l7proto_destory(Conntrack *p_st_ct)
{
    if(p_st_ct == NULL)
        return;

    //主动close时,已经更新状态
    if(p_st_ct->flg_status != APM_CONNECT_CLOSED)
        __frct_stat_system_lst_update(p_st_ct, 0, 0, 0, 0, 1);

    frlist_remove_all(&p_st_ct->lst_hdr_l7proto ,frct_l7proto_node_free);
    return;
}

/*******************************************************************************
*  FUNC     :  在指定协议中查询,如果查询到则设定
*  ARGS     :  p_st_ct              (Conntrack *)
            :  p_st_lst_hdr         (检查链表 节点存放Frmodule_mng)
            :  p_st_module_mng_exp  (如果和该节点一致,则跳过该节点,可以为NULL)
*  RTN      :  成功:返回管理节点Frmodule_mng ; FR_FAIL:NULL
*  NOTE     :
*******************************************************************************/
FR_STATIC Frmodule_mng *__frproto_list_detect(Conntrack *p_st_ct, Analyze_data_in *p_st_data_in
                                            , Frlist_header *p_st_lst_hdr, Frmodule_mng *p_st_module_mng_exp)
{
    Frlist_node *p_st_node=NULL;
    Frmodule_mng *p_st_module_mng_tmp=NULL;
    int i_fun_ret;
    
    if(p_st_ct == NULL || p_st_lst_hdr == NULL)
        return NULL;

    p_st_node = FRLIST_FIRST_NODE(p_st_lst_hdr);
    while(p_st_node)
    {
        p_st_module_mng_tmp =  (Frmodule_mng*)FRLIST_GET_NODE_DATA(p_st_node);
        if( (p_st_module_mng_exp && p_st_module_mng_exp == p_st_module_mng_tmp)
            || p_st_module_mng_tmp==NULL || p_st_module_mng_tmp->st_l7_module.l7_is == NULL)
        {
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
            continue;
        }
        //协议识别
        i_fun_ret = p_st_module_mng_tmp->st_l7_module.l7_is(p_st_ct, p_st_data_in);
        //frdbg("[%s].is i_ret=%04x\n", p_st_module_mng_tmp->st_l7_module.p_module_name, i_fun_ret);
        if(i_fun_ret  == APM_L7_IS_YES)
        {
            return p_st_module_mng_tmp;
        }
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }
    
    return NULL;
}

/*******************************************************************************
*  FUNC     :  改变l7协议状态
*  ARGS     :  p_st_ct      (Conntrack *)
*  RTN      :  
*  NOTE     :
*******************************************************************************/
void frct_l7proto_change_status(Conntrack *p_st_ct
                               , int i_flag_module_status
                               , unsigned int ui_define_ver
                               , int i_flag_l7proto_status)
{
    if(p_st_ct == NULL)
        return;
    
    p_st_ct->i_flag_module_status = i_flag_module_status;
    p_st_ct->ui_define_ver = ui_define_ver;
    p_st_ct->i_flag_l7proto_status = i_flag_l7proto_status;
    
    return;
}

/*******************************************************************************
*  FUNC     :  第1层协议的判断
*  ARGS     :  p_st_ct      (Conntrack *)
            :  p_st_data_in (协议分析用数据)
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :  需要加锁( p_st_ct->lock)
*******************************************************************************/
int frproto_l7_detect_first(Conntrack *p_st_ct, Analyze_data_in *p_st_data_in)
{
    Frlist_header st_lst_hdr_define, st_lst_hdr_known, st_lst_hdr_pri, st_lst_hdr_general;
    Frlist_node *p_st_node=NULL;
    Frmodule_mng *p_st_module_mng_tmp=NULL, *p_st_module_mng_known=NULL, *p_st_module_mng_default=NULL;
    unsigned int ui_proto_mng_ver=0;
    int i_fun_ret;
    
    if(p_st_ct == NULL || p_st_data_in == NULL)
        return FR_FAIL;

    //不是第1层
    if( frct_l7proto_is_first(p_st_ct) == FR_FAIL)
        return FR_FAIL;

    frlist_header_init(&st_lst_hdr_define);
    frlist_header_init(&st_lst_hdr_known);
    frlist_header_init(&st_lst_hdr_pri);
    frlist_header_init(&st_lst_hdr_general);
    
    /*对于已经识别的协议，可能存在协议更新的情况，需要再次判断
     *对于协议识别识别的CT，也需要再次协议判断 */
    if(p_st_ct->i_flag_l7proto_status == APM_L7PROTO_STATUS_DONE
        || p_st_ct->i_flag_l7proto_status == APM_L7PROTO_STATUS_FAIL)
    {
        //协议由用户指定
        if(p_st_ct->i_flag_module_status == APM_MODULE_STATUS_DEFINE)
        {
            i_fun_ret = frproto_define_is_same(p_st_ct->ip_proto, p_st_ct->dst_ip, p_st_ct->dst_port, p_st_ct->ui_define_ver);
            if(i_fun_ret == FR_SUCC)
                return FR_SUCC;
            //获取用户指定的协议以及版本号
            frproto_define_get(p_st_ct->ip_proto, p_st_ct->dst_ip, p_st_ct->dst_port, &st_lst_hdr_define, &ui_proto_mng_ver);
            if(frlist_size(&st_lst_hdr_define) <= 0)
                return FR_SUCC;
            
            if(ui_proto_mng_ver == p_st_ct->ui_define_ver)
            {
                frlist_remove_all(&st_lst_hdr_define, NULL);
                return FR_SUCC;
            }
            __frct_l7proto_update_lst(p_st_ct, &st_lst_hdr_define);
            frct_l7proto_change_status(p_st_ct, APM_MODULE_STATUS_DEFINE, ui_proto_mng_ver, APM_L7PROTO_STATUS_DONE);
            
            frlist_remove_all(&st_lst_hdr_define, NULL);
            return FR_SUCC;
        }
        else //协议自己识别或未识别
        {
            //获取用户指定的协议
            frproto_define_get(p_st_ct->ip_proto, p_st_ct->dst_ip, p_st_ct->dst_port, &st_lst_hdr_define, &ui_proto_mng_ver);
            if(frlist_size(&st_lst_hdr_define) <= 0)
                return FR_SUCC;
            __frct_l7proto_update_lst(p_st_ct, &st_lst_hdr_define);
            frct_l7proto_change_status(p_st_ct, APM_MODULE_STATUS_DEFINE, ui_proto_mng_ver, APM_L7PROTO_STATUS_DONE);
            
            frlist_remove_all(&st_lst_hdr_define, NULL);
            return FR_SUCC;
        }
    }
    //协议没有识别,或还需要多次判断
    frproto_define_get(p_st_ct->ip_proto, p_st_ct->dst_ip, p_st_ct->dst_port, &st_lst_hdr_define, &ui_proto_mng_ver);
    
    //指定协议里存在
    if(frlist_size(&st_lst_hdr_define) > 0)
    {
        frct_l7proto_remove(p_st_ct, 0);
        __frct_l7proto_add_lst(p_st_ct, &st_lst_hdr_define);
        frct_l7proto_change_status(p_st_ct, APM_MODULE_STATUS_DEFINE, ui_proto_mng_ver, APM_L7PROTO_STATUS_DONE);
        frlist_remove_all(&st_lst_hdr_define, NULL);
        return FR_SUCC;
    }
    
    //协议自己识别
    //先用已经识别过的协议判断
    p_st_module_mng_known = NULL;
    frproto_known_get(p_st_ct->ip_proto, p_st_ct->dst_ip, p_st_ct->dst_port, &st_lst_hdr_known);
    if(frlist_size(&st_lst_hdr_known) > 0)
    {
        //只保存1个节点
        p_st_node = FRLIST_FIRST_NODE(&st_lst_hdr_known);
        if(p_st_node)
            p_st_module_mng_known = (Frmodule_mng*)FRLIST_GET_NODE_DATA(p_st_node);
        if(p_st_module_mng_known && p_st_module_mng_known->st_l7_module.l7_is)
        {
            i_fun_ret = p_st_module_mng_known->st_l7_module.l7_is(p_st_ct, p_st_data_in);
            frdbg("[%s].is i_ret=%04x\n", p_st_module_mng_known->st_l7_module.p_module_name, i_fun_ret);
            if(i_fun_ret  == APM_L7_IS_YES)
            {
                __frct_l7proto_add_one(p_st_ct, &p_st_module_mng_known->st_l7_module);
                frct_l7proto_change_status(p_st_ct, APM_MODULE_STATUS_AUOTODETECT, 0, APM_L7PROTO_STATUS_IN_PROGRESS);

                frlist_remove_all(&st_lst_hdr_known, NULL);
                return FR_SUCC;
            }
        }
    }
    frlist_remove_all(&st_lst_hdr_known, NULL);
    
    //获取按端口组织的优先检查协议链表和普通检查协议链表
    frproto_get_chklist(p_st_ct->ip_proto, p_st_ct->dst_port,p_st_ct->src_port, &st_lst_hdr_pri, &st_lst_hdr_general);

    //优先判断协议
    p_st_module_mng_tmp =  __frproto_list_detect(p_st_ct, p_st_data_in, &st_lst_hdr_pri, p_st_module_mng_known);
    //普通判断协议
    if(p_st_module_mng_tmp == NULL)
        p_st_module_mng_tmp =  __frproto_list_detect(p_st_ct, p_st_data_in, &st_lst_hdr_general, p_st_module_mng_known);
    
    i_fun_ret = FR_FAIL;
    if(p_st_module_mng_tmp)
    {
        __frct_l7proto_add_one(p_st_ct, &p_st_module_mng_tmp->st_l7_module);
        frct_l7proto_change_status(p_st_ct, APM_MODULE_STATUS_AUOTODETECT, 0, APM_L7PROTO_STATUS_IN_PROGRESS);

        i_fun_ret = FR_SUCC;
    }
    else
    {
        //超过最大失败次数,设定为默认协议
        if(p_st_ct->ui_done_data_cnt >= st_apm_params.ui_l7_detect_max_times)
        {
            p_st_module_mng_default = frproto_l7default_find(p_st_ct->ip_proto);
            if(p_st_module_mng_default == NULL)
                p_st_module_mng_default = frproto_l7default_find(IPPROTO_TCP|IPPROTO_UDP);

            if(p_st_module_mng_default)
            {
                //frdbg("proto_chk_cnt=%d use default module %s\n", p_st_ct->ui_l7_proto_chk_cnt, p_st_module_mng_default->p_so_name);
                __frct_l7proto_add_one(p_st_ct, &p_st_module_mng_default->st_l7_module);
                p_st_ct->i_flag_l7proto_status = APM_L7PROTO_STATUS_DONE;
                p_st_ct->i_flag_queue_redo = FR_YES;
                p_st_ct->i_flag_peek2queue = FR_YES;
            }
            else
                p_st_ct->i_flag_l7proto_status = APM_L7PROTO_STATUS_FAIL;
        }
    }
    
    frlist_remove_all(&st_lst_hdr_pri, NULL);
    frlist_remove_all(&st_lst_hdr_general, NULL);
    
    return i_fun_ret;
}


/*******************************************************************************
*  FUNC     :  第2层以及这之上协议的判断
*  ARGS     :  p_st_ct      (Conntrack *)
            :  p_st_data_in (协议分析用数据)
*  RTN      :  FR_SUCC:成功,FR_FAIL:失败
*  NOTE     :  需要加锁( p_st_ct->lock)
*******************************************************************************/
int frproto_l7_detect_next(Conntrack *p_st_ct, Analyze_data_in *p_st_data_in)
{
    Frlist_header st_lst_hdr_pri, st_lst_hdr_general;
    Frmodule_mng *p_st_module_mng_tmp=NULL;
    int i_ret;
    
    if(p_st_ct == NULL || p_st_data_in == NULL)
        return FR_FAIL;

    //第1层时退出
    if( frct_l7proto_is_first(p_st_ct) == FR_SUCC)
        return FR_FAIL;
    
    if( p_st_ct->i_flag_l7proto_status == APM_L7PROTO_STATUS_DONE)
        return FR_SUCC;
        
    frlist_header_init(&st_lst_hdr_pri);
    frlist_header_init(&st_lst_hdr_general);
    
    //获取按端口组织的优先检查协议链表和普通检查协议链表
    frproto_get_chklist(p_st_ct->ip_proto, p_st_ct->dst_port,p_st_ct->src_port, &st_lst_hdr_pri, &st_lst_hdr_general);

    //优先判断协议
    p_st_module_mng_tmp =  __frproto_list_detect(p_st_ct, p_st_data_in, &st_lst_hdr_pri, NULL);
    //普通判断协议
    if(p_st_module_mng_tmp == NULL)
        p_st_module_mng_tmp =  __frproto_list_detect(p_st_ct, p_st_data_in, &st_lst_hdr_general, NULL);
    
    i_ret = FR_FAIL;
    if(p_st_module_mng_tmp)
    {
        __frct_l7proto_add_one(p_st_ct, &p_st_module_mng_tmp->st_l7_module);
        frct_l7proto_change_status(p_st_ct, APM_MODULE_STATUS_AUOTODETECT, 0, APM_L7PROTO_STATUS_IN_PROGRESS);

        i_ret = FR_SUCC;
    }
    else
    {
        //结束协议判断
        frct_l7proto_change_status(p_st_ct, APM_MODULE_STATUS_AUOTODETECT, 0, APM_L7PROTO_STATUS_DONE);
    }
    
    frlist_remove_all(&st_lst_hdr_pri, NULL);
    frlist_remove_all(&st_lst_hdr_general, NULL);
    
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  协议解码
*  ARGS     :  p_st_ct       (Conntrack *)
*           :  p_st_data_in  (Analyz_data_in *, 协议判断用数据)
*           :  p_st_data_out (Analyz_data_out *, 解析后出力数据)
*  RTN      :  l7_analyze的返回值
*  NOTE     :
*******************************************************************************/
int frproto_l7_analyze(Conntrack *p_st_ct
                     , Analyze_data_in *p_st_data_in
                     , Frhash_header  *p_st_hash_report
                     , Frlist_header  *p_st_list_output)
{
    L7_analyzer *p_st_l7_analyzer=NULL;
    L7_module *p_st_l7_module=NULL;
    int i_ret_fun=APM_L7_ANALYZE_FAIL;
    int i_requests=0, i_responses=0, i_succs=0, i_fails = 0;
    
    if(p_st_ct == NULL || p_st_data_in == NULL
        || p_st_hash_report==NULL || p_st_list_output == NULL )
        return APM_L7_ANALYZE_FAIL;

    p_st_l7_analyzer = frproto_l7_get_analyzer(p_st_ct);
    if(p_st_l7_analyzer)
        p_st_l7_module = p_st_l7_analyzer->p_st_l7_module;
    if(p_st_l7_module == NULL || p_st_l7_module->l7_analyze == NULL)
        return APM_L7_ANALYZE_FAIL;

    i_ret_fun = p_st_l7_module->l7_analyze(p_st_ct, p_st_data_in, p_st_hash_report, p_st_list_output);
    //frdbg("p_st_l7_module->l7_analyze=%p ret=%d\n", p_st_l7_module->l7_analyze, i_ret_fun);
    switch(i_ret_fun)
    {
        case APM_L7_ANALYZE_REDETECT:
            i_succs = 1;
            break;
        case APM_L7_ANALYZE_FAIL:
            i_fails = 1;
            break;
        default:
            if( APM_L7_ANALYZE_IS_SUCC(i_ret_fun) )
                i_succs = 1;
            if( APM_L7_ANALYZE_IS_REQ(i_ret_fun) )
                i_requests = 1;
            if( APM_L7_ANALYZE_IS_RESP(i_ret_fun) )
                i_responses = 1;
    }
    if(i_requests > 0 || i_responses > 0 || i_succs > 0  || i_fails > 0 )
        frstat_module_add(p_st_ct->ip_proto, p_st_l7_module->i_l7_proto, i_requests, i_responses, i_succs, i_fails);
    
    return i_ret_fun;
}

